package com.zhentao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhentao.dto.DoctorInfoDTO;
import com.zhentao.dto.DoctorLoginDTO;
import com.zhentao.dto.DoctorPasswordChangeDTO;
import com.zhentao.dto.DoctorRegisterDTO;
import com.zhentao.pojo.Doctor;
import com.zhentao.pojo.UserFaceInfo;
import com.zhentao.service.DoctorService;
import com.zhentao.service.UserFaceInfoService;
import com.zhentao.mapper.DoctorMapper;
import com.zhentao.util.MD5PasswordUtil;
import com.zhentao.util.MinioUtil;
import com.zhentao.vo.DoctorLoginVO;
import com.zhentao.vo.DoctorProfileVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* @author Administrator
* @description 针对表【doctor】的数据库操作Service实现
* @createDate 2025-09-21 19:08:24
*/
@Slf4j
@Service
public class DoctorServiceImpl extends ServiceImpl<DoctorMapper, Doctor>
    implements DoctorService{

    @Autowired
    private MD5PasswordUtil md5PasswordUtil;
    
    @Autowired
    private UserFaceInfoService userFaceInfoService;
    
    @Autowired
    private MinioUtil minioUtil;

    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public DoctorLoginVO login(DoctorLoginDTO loginDTO) {
        try {
            log.info("医生登录：{}", loginDTO.getDoctorName());
            
            // 根据医生姓名查询医生信息
            LambdaQueryWrapper<Doctor> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Doctor::getDoctorName, loginDTO.getDoctorName());
            Doctor doctor = this.getOne(queryWrapper);
            
            if (doctor == null) {
                throw new RuntimeException("用户不存在");
            }
            
            // 验证密码
            boolean passwordValid = md5PasswordUtil.verifyPassword(
                loginDTO.getPassword(), 
                doctor.getPassword(), 
                doctor.getSalt()
            );
            
            if (!passwordValid) {
                throw new RuntimeException("密码错误");
            }
            
            // 检查用户状态
            if (doctor.getStatus() != null && doctor.getStatus() == 3) {
                throw new RuntimeException("账户已离职，无法登录");
            }
            if (doctor.getStatus() != null && doctor.getStatus() == 4) {
                throw new RuntimeException("账户已停职，无法登录");
            }
            
            // 构建登录成功返回信息
            DoctorLoginVO loginVO = new DoctorLoginVO();
            BeanUtils.copyProperties(doctor, loginVO);
            loginVO.setLoginTime(DATE_FORMAT.format(new Date()));
            
            log.info("医生登录成功：{}", loginDTO.getDoctorName());
            return loginVO;
            
        } catch (Exception e) {
            log.error("医生登录失败：{}", loginDTO.getDoctorName(), e);
            throw new RuntimeException("登录失败：" + e.getMessage());
        }
    }

    @Override
    public Doctor register(DoctorRegisterDTO registerDTO) {
        try {
            log.info("医生注册：{}", registerDTO.getDoctorName());
            
            // 检查用户名是否已存在
            LambdaQueryWrapper<Doctor> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Doctor::getDoctorName, registerDTO.getDoctorName());
            Doctor existDoctor = this.getOne(queryWrapper);
            
            if (existDoctor != null) {
                throw new RuntimeException("医生姓名已存在，请选择其他姓名");
            }
            
            // 验证人脸信息ID是否存在
            UserFaceInfo faceInfo = userFaceInfoService.getById(registerDTO.getFaceInfoId());
            if (faceInfo == null) {
                throw new RuntimeException("人脸信息不存在，请先进行人脸注册");
            }
            
            // 检查该人脸ID是否已被其他医生使用
            LambdaQueryWrapper<Doctor> faceQueryWrapper = new LambdaQueryWrapper<>();
            faceQueryWrapper.eq(Doctor::getFaceInfoId, registerDTO.getFaceInfoId());
            Doctor existFaceDoctor = this.getOne(faceQueryWrapper);
            if (existFaceDoctor != null) {
                throw new RuntimeException("该人脸信息已被其他医生使用");
            }
            
            // 生成盐值和加密密码
            String salt = md5PasswordUtil.generateSalt();
            String encryptedPassword = md5PasswordUtil.encryptPassword(registerDTO.getPassword(), salt);
            
            // 创建医生信息
            Doctor doctor = new Doctor();
            doctor.setDoctorName(registerDTO.getDoctorName());
            doctor.setPassword(encryptedPassword);
            doctor.setSalt(salt);
            doctor.setFaceInfoId(registerDTO.getFaceInfoId()); // 设置人脸ID
            doctor.setDeptId(registerDTO.getDeptId()); // 设置部门ID
            doctor.setStatus(1); // 默认在职状态
            doctor.setCreateTime(new Date());
            doctor.setUpdateTime(new Date());
            
            // 保存到数据库
            boolean success = this.save(doctor);
            if (!success) {
                throw new RuntimeException("注册失败，请稍后重试");
            }
            
            // 更新人脸信息表中的姓名字段
            updateFaceInfoName(registerDTO.getFaceInfoId(), registerDTO.getDoctorName());
            
            log.info("医生注册成功：{}, ID: {}, 人脸ID: {}", registerDTO.getDoctorName(), doctor.getDoctorId(), registerDTO.getFaceInfoId());
            return doctor;
            
        } catch (Exception e) {
            log.error("医生注册失败：{}", registerDTO.getDoctorName(), e);
            throw new RuntimeException("注册失败：" + e.getMessage());
        }
    }

    @Override
    public boolean updateProfile(Integer doctorId, DoctorInfoDTO infoDTO) {
        try {
            log.info("更新医生个人信息：doctorId={}", doctorId);
            
            // 检查医生是否存在
            Doctor doctor = this.getById(doctorId);
            if (doctor == null) {
                throw new RuntimeException("医生不存在");
            }
            
            // 更新医生信息
            LambdaUpdateWrapper<Doctor> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Doctor::getDoctorId, doctorId);
            
            Doctor updateDoctor = new Doctor();
            updateDoctor.setAge(infoDTO.getAge());
            updateDoctor.setEmail(infoDTO.getEmail());
            updateDoctor.setGender(infoDTO.getGender());
            updateDoctor.setPhone(infoDTO.getPhone());
            updateDoctor.setDoctorNo(infoDTO.getDoctorNo());
            updateDoctor.setDeptId(infoDTO.getDeptId());
            updateDoctor.setQualificationNo(infoDTO.getQualificationNo());
            updateDoctor.setIdCard(infoDTO.getIdCard());
            updateDoctor.setFaceInfoId(infoDTO.getFaceInfoId());
            updateDoctor.setUpdateTime(new Date());
            
            boolean success = this.update(updateDoctor, updateWrapper);
            if (!success) {
                throw new RuntimeException("更新失败");
            }
            
            // 同步更新user_face_info表中的相同字段（被动同步策略）
            syncUserFaceInfo(doctor, infoDTO);
            
            log.info("医生个人信息更新成功：doctorId={}", doctorId);
            return true;
            
        } catch (Exception e) {
            log.error("更新医生个人信息失败：doctorId={}", doctorId, e);
            throw new RuntimeException("更新失败：" + e.getMessage());
        }
    }

    @Override
    public DoctorProfileVO getProfile(Integer doctorId) {
        try {
            log.info("获取医生个人资料：doctorId={}", doctorId);
            
            Doctor doctor = this.getById(doctorId);
            if (doctor == null) {
                throw new RuntimeException("医生不存在");
            }
            
            DoctorProfileVO profileVO = new DoctorProfileVO();
            BeanUtils.copyProperties(doctor, profileVO);
            
            // 添加调试日志
            log.info("=== 医生资料查询调试信息 ===");
            log.info("原始Doctor对象 - doctorId: {}, path: {}", doctor.getDoctorId(), doctor.getPath());
            log.info("复制后ProfileVO - doctorId: {}, path: {}", profileVO.getDoctorId(), profileVO.getPath());
            log.info("获取医生个人资料成功：doctorId={}", doctorId);
            
            return profileVO;
            
        } catch (Exception e) {
            log.error("获取医生个人资料失败：doctorId={}", doctorId, e);
            throw new RuntimeException("获取个人资料失败：" + e.getMessage());
        }
    }


    /**
     * 更新人脸信息表中的姓名字段
     * 
     * @param faceInfoId 人脸信息ID
     * @param doctorName 医生姓名
     */
    private void updateFaceInfoName(Integer faceInfoId, String doctorName) {
        try {
            log.info("更新人脸信息表姓名：faceInfoId={}, doctorName={}", faceInfoId, doctorName);
            
            LambdaUpdateWrapper<UserFaceInfo> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(UserFaceInfo::getId, faceInfoId);
            
            UserFaceInfo updateUser = new UserFaceInfo();
            updateUser.setName(doctorName);
            updateUser.setUpdateTime(new Date());
            
            boolean success = userFaceInfoService.update(updateUser, updateWrapper);
            if (success) {
                log.info("成功更新人脸信息表姓名：faceInfoId={}", faceInfoId);
            } else {
                log.warn("更新人脸信息表姓名失败：faceInfoId={}", faceInfoId);
            }
            
        } catch (Exception e) {
            // 更新姓名失败不影响主业务，仅记录日志
            log.error("更新人脸信息表姓名异常：faceInfoId={}", faceInfoId, e);
        }
    }

    /**
     * 同步更新user_face_info表中的相同字段
     * 
     * @param doctor 医生信息
     * @param infoDTO 更新的信息
     */
    private void syncUserFaceInfo(Doctor doctor, DoctorInfoDTO infoDTO) {
        try {
            // 通过faceInfoId查询关联的user_face_info记录
            if (doctor.getFaceInfoId() != null) {
                UserFaceInfo userFaceInfo = userFaceInfoService.getById(doctor.getFaceInfoId());
                if (userFaceInfo != null) {
                    // 同步更新相同字段
                    LambdaUpdateWrapper<UserFaceInfo> updateWrapper = new LambdaUpdateWrapper<>();
                    updateWrapper.eq(UserFaceInfo::getId, doctor.getFaceInfoId());
                    
                    UserFaceInfo updateUser = new UserFaceInfo();
                    updateUser.setName(doctor.getDoctorName()); // doctorName -> name
                    updateUser.setAge(infoDTO.getAge());
                    updateUser.setEmail(infoDTO.getEmail());
                    updateUser.setGender(infoDTO.getGender());
                    updateUser.setPhoneNumber(infoDTO.getPhone()); // phone -> phoneNumber
                    updateUser.setUpdateTime(new Date());
                    
                    boolean syncSuccess = userFaceInfoService.update(updateUser, updateWrapper);
                    if (syncSuccess) {
                        log.info("成功同步更新user_face_info表：faceInfoId={}", doctor.getFaceInfoId());
                    } else {
                        log.warn("同步更新user_face_info表失败：faceInfoId={}", doctor.getFaceInfoId());
                    }
                }
            }
        } catch (Exception e) {
            // 同步失败不影响主业务，仅记录日志
            log.error("同步更新user_face_info表异常：doctorId={}", doctor.getDoctorId(), e);
        }
    }

    @Override
    public boolean changePassword(Integer doctorId, DoctorPasswordChangeDTO passwordChangeDTO) {
        try {
            log.info("医生修改密码：doctorId={}", doctorId);
            
            // 验证新密码与确认密码是否一致
            if (!passwordChangeDTO.getNewPassword().equals(passwordChangeDTO.getConfirmPassword())) {
                throw new RuntimeException("新密码与确认密码不一致");
            }
            
            // 检查医生是否存在
            Doctor doctor = this.getById(doctorId);
            if (doctor == null) {
                throw new RuntimeException("医生不存在");
            }
            
            // 验证当前密码
            boolean currentPasswordValid = md5PasswordUtil.verifyPassword(
                passwordChangeDTO.getCurrentPassword(), 
                doctor.getPassword(), 
                doctor.getSalt()
            );
            
            if (!currentPasswordValid) {
                throw new RuntimeException("当前密码错误");
            }
            
            // 检查新密码是否与当前密码相同
            boolean samePassword = md5PasswordUtil.verifyPassword(
                passwordChangeDTO.getNewPassword(), 
                doctor.getPassword(), 
                doctor.getSalt()
            );
            
            if (samePassword) {
                throw new RuntimeException("新密码不能与当前密码相同");
            }
            
            // 生成新的盐值和加密新密码
            String newSalt = md5PasswordUtil.generateSalt();
            String encryptedNewPassword = md5PasswordUtil.encryptPassword(passwordChangeDTO.getNewPassword(), newSalt);
            
            // 更新密码
            LambdaUpdateWrapper<Doctor> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Doctor::getDoctorId, doctorId);
            
            Doctor updateDoctor = new Doctor();
            updateDoctor.setPassword(encryptedNewPassword);
            updateDoctor.setSalt(newSalt);
            updateDoctor.setUpdateTime(new Date());
            
            boolean success = this.update(updateDoctor, updateWrapper);
            if (!success) {
                throw new RuntimeException("密码修改失败");
            }
            
            log.info("医生密码修改成功：doctorId={}", doctorId);
            return true;
            
        } catch (Exception e) {
            log.error("医生密码修改失败：doctorId={}", doctorId, e);
            throw new RuntimeException("密码修改失败：" + e.getMessage());
        }
    }

    @Override
    public String uploadAvatar(Integer doctorId, MultipartFile file) {
        try {
            log.info("医生上传头像：doctorId={}", doctorId);
            
            // 检查医生是否存在
            Doctor doctor = this.getById(doctorId);
            if (doctor == null) {
                throw new RuntimeException("医生不存在");
            }
            
            // 上传头像到MinIO
            String avatarUrl = minioUtil.uploadDoctorAvatar(file, doctorId);
            
            // 删除旧头像（如果存在）
            if (doctor.getPath() != null && !doctor.getPath().isEmpty()) {
                try {
                    minioUtil.deleteObjectByUrl(doctor.getPath());
                    log.info("删除旧头像成功：{}", doctor.getPath());
                } catch (Exception e) {
                    // 删除旧头像失败不影响主业务
                    log.warn("删除旧头像失败：{}", doctor.getPath(), e);
                }
            }
            
            // 更新医生头像路径
            LambdaUpdateWrapper<Doctor> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Doctor::getDoctorId, doctorId);
            
            Doctor updateDoctor = new Doctor();
            updateDoctor.setPath(avatarUrl);
            updateDoctor.setUpdateTime(new Date());
            
            log.info("=== 头像路径更新调试信息 ===");
            log.info("准备更新头像路径 - doctorId: {}, avatarUrl: {}", doctorId, avatarUrl);
            
            boolean success = this.update(updateDoctor, updateWrapper);
            if (!success) {
                throw new RuntimeException("头像路径更新失败");
            }
            
            // 验证更新结果
            Doctor updatedDoctor = this.getById(doctorId);
            log.info("更新后验证 - doctorId: {}, 数据库中的path: {}", doctorId, updatedDoctor.getPath());
            
            log.info("医生头像上传成功：doctorId={}, url={}", doctorId, avatarUrl);
            return avatarUrl;
            
        } catch (Exception e) {
            log.error("医生头像上传失败：doctorId={}", doctorId, e);
            throw new RuntimeException("头像上传失败：" + e.getMessage());
        }
    }
}




